#include <UnitTest++.h>
#include "../getvoltages.h"
#include "../job.h"
#include <iostream>
#include <string>
#include "../option.h"
#include "../MyMap.h"
#include "fixturesInputOutput.h"
#include <windows.h> // for the tickcout

using namespace std;

// Fixtures declared in "fixturesInputOutput.h"

//TEST(TriggeringPassAlways)
//{
//    CHECK(true);
//}
void printPreAndPostTrigger(SoftTrigJob* jobptr)
{
//    long postTrigSize = jobptr->getoptL("numchannels") * jobptr->getoptL("posttrigsamples");
    // cout << "Post Trigger array size is : " << postTrigSize << endl;
//    double* d = jobptr->getTestingArray();
    long preSize = jobptr->getPreTrigArraySize();
    double* preData = jobptr->getPreTrigArray();
    long postSize = jobptr->getPostTrigSize();
    double* postData = jobptr->getPostTrigData();
    //cout << ptSize << " -- " << ptData << endl;

    // print out pre and post trigger values as a diagnostic
    for(int i=preSize - 20; i < preSize; i++)
        cout << preData[i] << endl;

    cout << jobptr->getoptD("triggerlevel") << " <-- Triggerlevel" << endl;

    for(int i=0; i < 20; i++)
        cout << postData[i] << endl;
    return;
}
double trigSlopeToDouble(SoftTrigJob* jobptr)
{   double trigSlope = 1.0;
    if (jobptr->getoptL("triggerslope") == DAQmx_Val_FallingSlope)
        trigSlope = -1.0;
    return trigSlope;
}
bool preTrigOK(SoftTrigJob* jobptr) {
//    cout << "preTrigger data trig slogpe " << trigSlopeToDouble(jobptr) << " trig level " << jobptr->getoptD("triggerlevel") << " val " << jobptr->getPreTrigArray()[jobptr->getPreTrigArraySize() - 1] <<endl;
    return (trigSlopeToDouble(jobptr) * (jobptr->getoptD("triggerlevel") - jobptr->getPreTrigArray()[jobptr->getPreTrigArraySize() - 1]) > 0);}

bool postTrigOK(SoftTrigJob* jobptr) {
    return (trigSlopeToDouble(jobptr) * (jobptr->getPostTrigData()[0] - jobptr->getoptD("triggerlevel")) > 0);
}

TEST_FIXTURE(IOFixture, SoftwareTriggeringPositveSlopeFiniteSamplesNotTriggered) {
    // continuous sinewave defined in IOFixture
    OutputJob* outjobptr = ContinuousSineWave();

    // currently the conditions which cause wait for trigger to return are
    //  1) trigger condition met samples taken
    //  2) number of samples in testing array is reached if finite samples
    // * finite samples is general not used
//        cout << "samples = " << In.opt.L["samples"]  << endl;;

        In.opt.L["samples"] = 100;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.D["frequency"] = 15000.0;
        In.opt.L["posttrigsamples"] = 50;
        In.opt.D["triggerlevel"] = 1.30;  //Greater than signal max
        In.opt.L["samplemode"] = DAQmx_Val_FiniteSamps;
            //  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));

        long samplesPastTrigger = jobptr->waitForTrigger();
      //  cout << "samples read past trigger:" << samplesPastTrigger << endl;
        CHECK_EQUAL(-1, samplesPastTrigger); // TriggerLevel greater than max input signal

        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, SoftwareTriggedPositveSlopeContinuousPreAndPostTest) {
    // continuous sinewave defined in IOFixture
    OutputJob* outjobptr = ContinuousSineWave();
    //  !!!!!!!!!! DataAcquisiton package sets samples and pretrigsamples = !!!!!!!!!!!
    //  finite sample number may be causes problems likely because of sample number
        In.opt.L["samples"] = In.opt.L["pretrigsamples"] = 3;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.L["posttrigsamples"] = 10;
        In.opt.D["frequency"] = 1000.0;
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
            //  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));

        long samplesPastTrigger = jobptr->waitForTrigger();
        CHECK(samplesPastTrigger > 0);  // trigger condition met! one past trigger garunteed?

        jobptr->readPreTrigger();
        jobptr->readPostTrigger();

        //printPreAndPostTrigger(jobptr);
//        CHECK(preTrigOK(jobptr));
//        CHECK(postTrigOK(jobptr));

        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, SoftwareTriggedPositveSlopeContinuousNoPreTriggerSamaples) {
    OutputJob* outjobptr = ContinuousSineWave();// continuous sinewave defined in IOFixture

        In.opt.L["samples"] =  In.opt.L["pretrigsamples"] = 0;
        In.opt.L["posttrigsamples"] = 10;
        In.opt.D["frequency"] = 1000.0;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps; // DAQmx_Val_FiniteSamps has problems
    //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));

        jobptr->waitForTrigger();
        jobptr->readPreTrigger();
        jobptr->readPostTrigger();

        CHECK(postTrigOK(jobptr));
        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, SoftwareTriggedNegativeSlopeContinuousPreAndPostTest) {
    // continuous sinewave defined in IOFixture
    OutputJob* outjobptr = ContinuousSineWave();

        In.opt.L["samples"] = In.opt.L["pretrigsamples"] = 3;
        In.opt.L["posttrigsamples"] = 10;
        In.opt.D["frequency"] = 1000.0;
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
        CHECK_EQUAL(DAQmx_Val_Falling, DAQmx_Val_FallingSlope);
        In.opt.L["triggerslope"] = DAQmx_Val_FallingSlope;  //  or In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));


        long samplesPastTrigger = jobptr->waitForTrigger();
   //     cout << "samples read past trigger:" << samplesPastTrigger << endl;
        CHECK(samplesPastTrigger > 0);  // trigger condition met! one past trigger garunteed?

        jobptr->readPreTrigger();
        jobptr->readPostTrigger();

//        printPreAndPostTrigger(jobptr);
        CHECK(preTrigOK(jobptr));
        CHECK(postTrigOK(jobptr));

        delete jobptr;
    delete outjobptr;
}
TEST_FIXTURE(IOFixture, SoftwareTriggedCorrectNumberOfSamples) {
    // continuous sinewave defined in IOFixture
    OutputJob* outjobptr = ContinuousSineWave(2.00, 5000.0);
    //  !!!!!!!!!! DataAcquisiton package sets samples and pretrigsamples = !!!!!!!!!!!
    //  finite sample number may be causes problems likely because of sample number
        In.opt.L["samples"] = 0;
        In.opt.L["pretrigsamples"] = 30;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.L["posttrigsamples"] = 50;
        In.opt.D["frequency"] = 1000.0;          //2000 is too fast for MinGW_TDM with small buffer
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
            //  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));

        long samplesPastTrigger = jobptr->waitForTrigger();
        CHECK(samplesPastTrigger > -1);  // trigger condition met! one past trigger garunteed?
//        std::cout << "samplesPastTrigger= " << samplesPastTrigger << std::endl;
        jobptr->readPreTrigger();
        jobptr->readPostTrigger();

//        cout << "getPreTrigArraySize() = " << jobptr->getPreTrigArraySize() << endl;
//        cout << "getTestingArraySize() = "<< jobptr->getTestingArraySize() << endl;
//        cout << "getoptL(\"posttrigsamples\")  = "<< jobptr->getoptL("posttrigsamples") << endl;
//        cout << "getoptL(\"pretrigsamples\")  = "<< jobptr->getoptL("pretrigsamples") << endl;
//        CHECK_EQUAL(jobptr->getoptL("pretrigsamples"), jobptr->getPreTrigArraySize());
//        printPreAndPostTrigger(jobptr);
        CHECK(preTrigOK(jobptr));
        CHECK(postTrigOK(jobptr));

        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, DigitalTriggeredPositveSlopeFinite) {
    //* Currently no pretriggersamples for Digital Triggering
    // does not work from Mathematica test package as of 4/20 alos finite samples works continuous does not


    OutputJob* outjobptr = ContinuousSineWave(4.0, 10000.0);  // continuous sinewave defined in IOFixture
    //  !!!!!!!!!! DataAcquisiton package sets samples and pretrigsamples = !!!!!!!!!!!
    //  finite sample number may be causes problems likely because of sample number
        //In.opt.L["samples"] = 100;
        long preT = In.opt.L["pretrigsamples"] = 10;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.S["triggersource"] = "PFI0";
        In.opt.L["posttrigsamples"] = 100;
        In.opt.D["frequency"] = 5000.0;
        In.opt.L["samplemode"] = DAQmx_Val_FiniteSamps;
      //*************  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

		DigitalTrigJob* jobptr = new DigitalTrigJob("Digital Triggering", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));
        CHECK(jobptr->isDoneNoError());
        jobptr->readData();
//       double* data = jobptr->getPostTrigData();
//        cout << jobptr->getSampleArraySize() << endl;
//        for(int i=0; i<20; i++)
//            cout << data[i] << endl;

        if (In.opt.L["triggerslope"] == DAQmx_Val_RisingSlope)
            CHECK(jobptr->getTestData()[preT] < jobptr->getTestData()[preT + 1]);
        if (In.opt.L["triggerslope"] == DAQmx_Val_FallingSlope)
            CHECK(jobptr->getTestData()[preT] > jobptr->getTestData()[preT+1]);

//        //printPreAndTestger(jobptr);
//        CHECK(preTrigOK(jobptr));
//        CHECK(TestOK(jobptr));

        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, DigitalTriggeredNegativeSlopeFinite) {
    //* Currently no pretriggersamples for Digital Triggering
    // does not work from Mathematica test package as of 4/20 alos finite samples works continuous does not


    OutputJob* outjobptr = ContinuousSineWave(4.0, 5000.0);  // continuous sinewave defined in IOFixture
    //  !!!!!!!!!! DataAcquisiton package sets samples and pretrigsamples = !!!!!!!!!!!
    //  finite sample number may be causes problems likely because of sample number
        //In.opt.L["samples"] = 100;
        In.opt.L["pretrigsamples"] = 10;
        In.opt.L["triggerslope"] = DAQmx_Val_FallingSlope;
        In.opt.S["triggersource"] = "PFI0";
        In.opt.L["posttrigsamples"] = 100;
        In.opt.D["frequency"] = 2000.0;
        In.opt.L["samplemode"] = DAQmx_Val_FiniteSamps;
      //*************  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
//        cout << In.opt.toString() << endl;

		DigitalTrigJob* jobptr = new DigitalTrigJob("Digital Triggering", persistJobs, In.opt);
		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));
        CHECK(jobptr->isDoneNoError());
        jobptr->readData();
        double* data = jobptr->getTestData();
 //       cout << jobptr->getSampleArraySize() << endl;
//        for(int i=0; i<20; i++)
//            cout << data[i] << endl;

        if (In.opt.L["triggerslope"] == DAQmx_Val_RisingSlope)
            CHECK(jobptr->getTestData()[In.opt.L["pretrigsamples"]] < jobptr->getTestData()[In.opt.L["pretrigsamples"] + 1]);
        if (In.opt.L["triggerslope"] == DAQmx_Val_FallingSlope)
            CHECK(jobptr->getTestData()[In.opt.L["pretrigsamples"]] > jobptr->getTestData()[In.opt.L["pretrigsamples"] + 1]);

//        //printPreAndPostTrigger(jobptr);
//        CHECK(preTrigOK(jobptr));
//       CHECK(postTrigOK(jobptr));

        delete jobptr;
    delete outjobptr;
}

TEST(arrayHolderCreation)
{
    arrayHolder ah(GROUPBYSCAN, 10, 1);
    CHECK_EQUAL(10, ah.getSize());
}

TEST(arrayHolderStoreDAta)
{
    arrayHolder ah(GROUPBYSCAN, 10, 1);
    ah.getData()[0] = 22.0;
    CHECK_EQUAL(22, ah.getData()[0]);
}

TEST_FIXTURE(IOFixture, TriggerTestOnFakeData) {

    // currently the conditions which cause wait for trigger to return are
    //  1) trigger condition met samples taken
    //  2) number of samples in testing array is reached if finite samples
    // * finite samples is general not used
//        cout << "samples = " << In.opt.L["samples"]  << endl;;
        In.opt.L["samples"] = 5;
        In.opt.L["triggerslope"] = DAQmx_Val_RisingSlope;
        In.opt.D["frequency"] = 1000.0;
        In.opt.L["posttrigsamples"] = 5;
        In.opt.D["triggerlevel"] = 2.50;  //Greater than signal max
        In.opt.L["samplemode"] = DAQmx_Val_FiniteSamps;
            //  In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
            //  cout << In.opt.toString() << endl;

		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
		double *pData = jobptr->getTestingArray();
        double  fakeData[]={0,0,0,0,1,2,3,4,5,6,7,8,9};
        long fakeSize = sizeof(fakeData)/sizeof(fakeData[0]);
        for(int i=0; i < fakeSize; i++)
            pData[i] =fakeData[i];
//        for(int i=0; i < fakeSize; i++)
//            cout << pData[i] << (i == fakeSize-1 ? "\n" : ", ");
        long readPastTrigger;
        TrigTest tt(*jobptr, readPastTrigger);

        CHECK_EQUAL(tt.IsTriggered(6), false);
        CHECK_EQUAL(tt.IsTriggered(7), true);
        CHECK_EQUAL(tt.IsTriggered(6 + 4 ), true);
        CHECK_EQUAL(4, readPastTrigger);
//        cout << "readPastTrigger: " << readPastTrigger << endl;

        delete jobptr;
}
TEST_FIXTURE(IOFixture, SoftwareTriggedTestTiming) {
    // continuous sinewave defined in IOFixture
    double outputfreq = 5000.0;
    OutputJob* outjobptr = ContinuousSineWave(2.00, outputfreq);
    const long millisecsPerTick = 16;
    long start_time, stop_time;

        In.opt.L["samples"] = 0;    // samples -1 causes program to hang set samples = pretrigsamples safest
                                    // 0 causes no problems?
        In.opt.L["pretrigsamples"] = 50;
        In.opt.L["posttrigsamples"] = 100;
        In.opt.D["frequency"] = 5000.0;
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
        CHECK_EQUAL(10123, DAQmx_Val_ContSamps);

        In.opt.L["triggerslope"] = DAQmx_Val_Falling;  //  or In.opt.L["samplemode"] = DAQmx_Val_ContSamps;
    //  cout << In.opt.toString() << endl;

        start_time = GetTickCount();
		SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);

		CHECK(jobptr != 0);  CHECK(jobptr->getTaskHandle() !=0);
        CHECK_EQUAL(0, jobptr->startTask(jobptr->getTaskHandle()));
        int32 samplemode = 0;
        DAQmxGetSampQuantSampMode(jobptr->getTaskHandle(), &samplemode);
        CHECK_EQUAL(DAQmx_Val_ContSamps, samplemode);

        stop_time = GetTickCount();
    //    cout << "creation time and start task time= " << stop_time - start_time << " in milliseconds" << endl;
        CHECK(2 * millisecsPerTick > stop_time - start_time);

        start_time = GetTickCount();
        long samplesPastTrigger = jobptr->waitForTrigger();
        stop_time = GetTickCount();
     //   cout << "wait for trigger time = " << stop_time - start_time << " in milliseconds" << endl;
        CHECK((In.opt.L["pretrigsamples"] / In.opt.D["frequency"]  * 1000.0  - 2 * millisecsPerTick) < (stop_time - start_time));
        CHECK((In.opt.L["pretrigsamples"] / In.opt.D["frequency"]  * 1000.0  + numPts/outputfreq * 1000.0 + 2 * millisecsPerTick) > (stop_time - start_time));
        //cout << In.opt.L["pretrigsamples"] / In.opt.D["frequency"]  * 1000.0  + numPts/outputfreq * 1000.0 + 2 * millisecsPerTick << endl;

   //     cout << "samples read past trigger:" << samplesPastTrigger << endl;
        CHECK(samplesPastTrigger > 0);  // trigger condition met! one past trigger garunteed?

        start_time = GetTickCount();
        jobptr->readPreTrigger();
        jobptr->readPostTrigger();
        stop_time = GetTickCount();
        //cout << "read time = " << stop_time - start_time << " in milliseconds" << endl;
        CHECK((In.opt.L["posttrigsamples"] / In.opt.D["frequency"]  * 1000.0  - 5* millisecsPerTick) < (stop_time - start_time));
        CHECK((In.opt.L["posttrigsamples"] / In.opt.D["frequency"]  * 1000.0  + 2 * millisecsPerTick) > (stop_time - start_time));


      //  printPreAndPostTrigger(jobptr);
        CHECK(preTrigOK(jobptr));
        CHECK(postTrigOK(jobptr));

        delete jobptr;
    delete outjobptr;
}

TEST_FIXTURE(IOFixture, SoftwareTriggeredTransferPropertiesCheck) {
    double outputfreq = 1000.0;
    OutputJob* outjobptr = ContinuousSineWave(2.00, outputfreq);

        In.opt.L["samples"] = 0;    // samples -1 causes program to hang set samples = pretrigsamples safest
                                    // 0 causes no problems?
        In.opt.L["pretrigsamples"] = 5000;
        In.opt.L["posttrigsamples"] = 1000;
        In.opt.D["frequency"] = 30000.0;        //if frequency < 20 KHz use on board memory not empty with interrupts
        In.opt.D["triggerlevel"] = 0.60;  // In signal range
        In.opt.L["samplemode"] = DAQmx_Val_ContSamps;

        int32 transferMode = 0, transferCondition;

        In.opt.L["transfermech"] = DAQmx_Val_Interrupts;
            SoftTrigJob* jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
            DAQmxGetAIDataXferMech(jobptr->getTaskHandle(), jobptr->getoptS("channels").c_str(), &transferMode);
            CHECK_EQUAL(In.opt.L["transfermech"], transferMode);

            DAQmxGetAIDataXferReqCond(jobptr->getTaskHandle(), jobptr->getoptS("channels").c_str(), &transferCondition);
            CHECK_EQUAL(DAQmx_Val_OnBrdMemMoreThanHalfFull , transferCondition);
            delete jobptr;

        In.opt.L["transfermech"] = DAQmx_Val_DMA;
            jobptr = new SoftTrigJob("Sotware Triggered array", persistJobs, In.opt);
            DAQmxGetAIDataXferMech(jobptr->getTaskHandle(), jobptr->getoptS("channels").c_str(), &transferMode);
            CHECK_EQUAL(In.opt.L["transfermech"], transferMode);

            DAQmxGetAIDataXferReqCond(jobptr->getTaskHandle(), jobptr->getoptS("channels").c_str(), &transferCondition);
            CHECK_EQUAL(DAQmx_Val_OnBrdMemNotEmpty, transferCondition);
          //  cout << "Transfer condition = " << transferCondition <<endl;
            delete jobptr;

    delete outjobptr;
}

TEST(InterruptsTransferBlockSize)
//**** Note: default for DMA is DAQmx_Val_OnBrdMemNotEmpty while
//*   Default for Interrupts is DAQmx_Val_OnBrdMemMoreThanHalfFull  == 2048 samples
{
    TaskHandle taskHandle;
    int32 iErr = -1;

    char errMsg[1000];
    iErr = DAQmxCreateTask ("DMABlockSize", &taskHandle);CHECK_EQUAL(0, iErr);

    double frequency = 1000.0;
    const long sampleNumber = 10000; // at 100Hz 100000=2048, 10000=2048, 1000=2048 as meassured by time., 100 =2048 as meassured by time
    double buf[sampleNumber];

    iErr=DAQmxCreateAIVoltageChan(taskHandle,
		"Dev1/ai0",
		NULL,
		DAQmx_Val_Diff,
		-10.0,
		+10.0,
		DAQmx_Val_Volts,
		NULL); CHECK_EQUAL(0, iErr);


    iErr = DAQmxCfgSampClkTiming (taskHandle,
		"OnboardClock",
		frequency,
		DAQmx_Val_RisingSlope,
		DAQmx_Val_ContSamps,
		10); CHECK_EQUAL(0, iErr);

    int32 setTransferMode = DAQmx_Val_Interrupts;   // DAQmx_Val_Interrupts or default value of DAQmx_Val_DMA
    iErr = DAQmxSetAIDataXferMech(taskHandle, "Dev1/ai0", setTransferMode); CHECK_EQUAL(0, iErr);

    iErr = DAQmxSetAIDataXferReqCond(taskHandle, "Dev1/ai0", DAQmx_Val_OnBrdMemNotEmpty); CHECK_EQUAL(0, iErr);

    int32 transferMode = 0;
    iErr = DAQmxGetAIDataXferMech(taskHandle, "Dev1/ai0", &transferMode); CHECK_EQUAL(0, iErr);
    CHECK_EQUAL(setTransferMode, transferMode);

    long samplesRead = 0;
    long totalRead = 0;

    while (totalRead < 50 && iErr == 0)
    {
        iErr = DAQmxReadAnalogF64(
            taskHandle,
            -1,
            3.0,
            DAQmx_Val_GroupByChannel,
            buf,
            sampleNumber,
            &samplesRead,
            NULL
		);
		totalRead += samplesRead;
		if (samplesRead !=0){
//            cout << "Samples read: " << samplesRead << " and current total: " << totalRead << endl;
            CHECK(samplesRead < 20);
		}
    }
    CHECK_EQUAL(0, iErr);
    cout << endl;
  //  DAQmxGetExtendedErrorInfo(errMsg, 1000);
  //  cout << errMsg << endl;

    iErr = DAQmxClearTask(taskHandle); CHECK_EQUAL(0, iErr);
}


